﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IdentityModel.Client;
using IdentityServer4;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Yuan.MVC.Demo.Models;
using BaseController = Microsoft.AspNetCore.Mvc;
namespace Yuan.MVC.Demo.Controllers
{

    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        // private readonly UserManager<IdentityUser> _userManager;
        public HomeController(ILogger<HomeController> logger
            //  , UserManager<IdentityUser> userManager
            )
        {
            _logger = logger;
            //_userManager = userManager;
        }

        public IActionResult Index()
        {
            return View();
        }
        [Authorize]
        public IActionResult TestApi()
        {
            return Content("API 返回");
        }

        [Authorize]
        public async Task<IActionResult> Privacy()
        {
            ViewData["Message"] = "Secure page.";


            var sddd = from c in User.Claims select new { c.Type, c.Value };
            var user = HttpContext.User;
            var ssd = HttpContext.User.Claims;
            var clms = User.Claims;
            //var user = await _userManager.GetUserAsync(HttpContext.User);

            //var claims= await _userManager.GetClaimsAsync(user);

            //var role = await _userManager.GetRolesAsync(user);

            return View();
        }

        public IActionResult Logout()
        {
            return SignOut("Cookies", "oidc");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        /// <summary>
        /// 测试请求API资源(api1)
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> getApi()
        {
            var client = new HttpClient();
            var s = HttpContext.Request;
            var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
            if (string.IsNullOrEmpty(accessToken))
            {
                return Json(new { msg = "accesstoken 获取失败" });
            }

            client.SetBearerToken(accessToken);
            //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var httpResponse = await client.GetAsync("http://localhost:5001/api/identity/GetUserClaims");
            var result = await httpResponse.Content.ReadAsStringAsync();
            if (!httpResponse.IsSuccessStatusCode)
            {
                if (httpResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    await GetNewToken();//刷新Token
                    return RedirectToAction();//刷新当前页
                }
                return Json(new { msg = "请求 api1 失败。", error = result });
            }
            return Content(result);
            //return Json(new
            //{
            //    msg = "成功",
            //    data = JsonConvert.DeserializeObject(result)
            //});
        }

        /// <summary>
        /// 刷新AcceccToken
        /// </summary>
        /// <returns>AcceccToken</returns>
        private async Task<string> GetNewToken()
        {
            var client = new HttpClient();
            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5002");
            if (disco.IsError)
                throw new Exception(disco.Error);
            var refreshToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
            var newToken = await client.RequestRefreshTokenAsync(new RefreshTokenRequest()
            {
                ClientId = "code_client",
                Address = disco.TokenEndpoint,
                ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
                //Scope = $@"code_scope1 {IdentityServerConstants.StandardScopes.Profile} {IdentityServerConstants.StandardScopes.OfflineAccess} 
                //         {IdentityServerConstants.StandardScopes.OpenId} {IdentityServerConstants.StandardScopes.Address}",
                GrantType = OpenIdConnectGrantTypes.RefreshToken,
                RefreshToken = refreshToken
            });
            if (newToken.IsError)
                throw new Exception(newToken.Error);

            var expire_at = DateTime.UtcNow + TimeSpan.FromSeconds(newToken.ExpiresIn);

            var tokens = new List<AuthenticationToken>()
            {
                new AuthenticationToken(){  Name=OpenIdConnectParameterNames.IdToken ,Value= newToken.IdentityToken},
                new AuthenticationToken(){  Name=OpenIdConnectParameterNames.AccessToken ,Value= newToken.AccessToken},
                new AuthenticationToken(){  Name=OpenIdConnectParameterNames.RefreshToken ,Value= newToken.RefreshToken},
                new AuthenticationToken(){  Name="expire_at",Value= expire_at.ToString("o",System.Globalization.CultureInfo.InvariantCulture)}
            };
            var currentAuth = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            currentAuth.Properties.StoreTokens(tokens);

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, currentAuth.Principal, currentAuth.Properties);
            return newToken.AccessToken;
        }
    }
}
